package com.xuan.bigappleui.lib.view.photoview.gestures;

import android.content.Context;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;

public class BUCupcakeGestureDetector implements BUGestureDetector {

	protected BUOnGestureListener mListener;
	private static final String LOG_TAG = "CupcakeGestureDetector";
	float mLastTouchX;
	float mLastTouchY;
	final float mTouchSlop;
	final float mMinimumVelocity;

	@Override
	public void setOnGestureListener(BUOnGestureListener listener) {
		this.mListener = listener;
	}

	public BUCupcakeGestureDetector(Context context) {
		final ViewConfiguration configuration = ViewConfiguration.get(context);
		mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
		mTouchSlop = configuration.getScaledTouchSlop();
	}

	private VelocityTracker mVelocityTracker;
	private boolean mIsDragging;

	float getActiveX(MotionEvent ev) {
		return ev.getX();
	}

	float getActiveY(MotionEvent ev) {
		return ev.getY();
	}

	@Override
	public boolean isScaling() {
		return false;
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN: {
			mVelocityTracker = VelocityTracker.obtain();
			if (null != mVelocityTracker) {
				mVelocityTracker.addMovement(ev);
			} else {
				Log.i(LOG_TAG, "Velocity tracker is null");
			}

			mLastTouchX = getActiveX(ev);
			mLastTouchY = getActiveY(ev);
			mIsDragging = false;
			break;
		}

		case MotionEvent.ACTION_MOVE: {
			final float x = getActiveX(ev);
			final float y = getActiveY(ev);
			final float dx = x - mLastTouchX, dy = y - mLastTouchY;

			if (!mIsDragging) {
				// Use Pythagoras to see if drag length is larger than
				// touch slop
				mIsDragging = FloatMath.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
			}

			if (mIsDragging) {
				mListener.onDrag(dx, dy);
				mLastTouchX = x;
				mLastTouchY = y;

				if (null != mVelocityTracker) {
					mVelocityTracker.addMovement(ev);
				}
			}
			break;
		}

		case MotionEvent.ACTION_CANCEL: {
			// Recycle Velocity Tracker
			if (null != mVelocityTracker) {
				mVelocityTracker.recycle();
				mVelocityTracker = null;
			}
			break;
		}

		case MotionEvent.ACTION_UP: {
			if (mIsDragging) {
				if (null != mVelocityTracker) {
					mLastTouchX = getActiveX(ev);
					mLastTouchY = getActiveY(ev);

					// Compute velocity within the last 1000ms
					mVelocityTracker.addMovement(ev);
					mVelocityTracker.computeCurrentVelocity(1000);

					final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker
							.getYVelocity();

					// If the velocity is greater than minVelocity, call
					// listener
					if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
						mListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);
					}
				}
			}

			// Recycle Velocity Tracker
			if (null != mVelocityTracker) {
				mVelocityTracker.recycle();
				mVelocityTracker = null;
			}
			break;
		}
		}

		return true;
	}

}
